package service

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"mogu-go-v2/common"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

/**
 *
 * @author  镜湖老杨
 * @date  2021/1/4 3:18 下午
 * @version 1.0
 */
type wechatService struct{}

// SenceRule 带参数二维码
type SenceRule struct {
	Scene     string `json:"scene"`
	Page      string `json:"page,omitempty"`
	Width     int    `json:"width,omitempty"`
	AutoColor bool   `json:"auto_color,omitempty"`
	LineColor string `json:"line_color,omitempty"`
	IsHyaline bool   `json:"is_hyaline,omitempty"`
}

// BufferRule 图片buffer
type BufferRule struct {
	Buffer []byte `json:"Buffer"`
}

// ReturnBodyRule 微信返回通过结果集
type ReturnBodyRule struct {
	ErrorCode    int    `json:"errcode,omitempty"`
	ErrorMessage string `json:"errmsg,omitempty"`
}

const CREATE_QRCODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s"

func (wechatService) GetAccessToken(appid, secret string) (string, error) {
	if len(appid) == 0 || len(secret) == 0 {
		return "", errors.New("appid或者secret为空")
	}

	accessToken := common.RedisUtil.Get("ACCESS_TOKEN_APPID:" + appid)
	if accessToken == "" {
		// 重新请求一下
		u, err := url.Parse("https://api.weixin.qq.com/cgi-bin/token")
		if err != nil {
			l.Print(err)
		}
		paras := &url.Values{}
		//设置请求参数
		paras.Set("appid", appid)
		paras.Set("secret", secret)
		paras.Set("grant_type", "client_credential")
		u.RawQuery = paras.Encode()
		resp, err := http.Get(u.String())
		//关闭资源
		if resp != nil && resp.Body != nil {
			defer resp.Body.Close()
		}
		if err != nil {
			return "", errors.New("request token err :" + err.Error())
		}

		jMap := make(map[string]interface{})
		err = json.NewDecoder(resp.Body).Decode(&jMap)
		if err != nil {
			return "", errors.New("request token response json parse err :" + err.Error())
		}
		if jMap["errcode"] == nil || jMap["errcode"] == 0 {
			accessToken, _ := jMap["access_token"].(string)
			common.RedisUtil.SetEx("ACCESS_TOKEN_APPID:"+appid, accessToken, 7000, time.Second)
			return accessToken, nil
		} else {
			//返回错误信息
			errcode := jMap["errcode"].(string)
			errmsg := jMap["errmsg"].(string)
			err = errors.New(errcode + ":" + errmsg)
			return "", err
		}
	} else {
		return accessToken, nil
	}
}

func (wechatService) GetWxacodeUnlimit(token, sence, fileName, page string) (string, error) {
	if len(token) == 0 || len(sence) == 0 {
		l.Print("参数为空-PostScene")
		return "", errors.New("参数为空-PostScene")
	}

	url := fmt.Sprintf(CREATE_QRCODE_URL, token)
	senceStruct := SenceRule{
		Scene: sence,
		Width: 430,
		Page:  page,
	}
	l.Print(url)

	jsonBody, jsonErr := json.Marshal(senceStruct)
	if jsonErr != nil {
		l.Print(jsonErr)
		return "", jsonErr
	}

	postBody, postErr := http.Post(url, "application/json; charset=utf-8", bytes.NewReader(jsonBody))
	if postErr != nil {
		l.Print(postErr)
		return "", postErr
	}
	//body, _ := ioutil.ReadAll(postBody.Body)
	//fmt.Println(string(body))
	//fmt.Println(postBody.Header.Get("Content-Type"))
	defer postBody.Body.Close()
	//imagePath := "user/qrcodeId/" + fileName
	// uuid := strconv.FormatInt(time.Now().Unix(), 10)
	//localPath, localPathErr := GetLocalPath("/public/upload/qrcode-xcx/")
	//if localPathErr != nil || len(localPath) == 0 {
	//	l.Print("本地路径-PostScene")
	//	//log.WithFields(log.Fields{"error": postErr}).Warn("本地路径-PostScene")
	//	return "", postErr
	//}
	//localPath += uuid + ".jpg"
	localPath := "static/upload/wxacode/" + fileName + ".jpg"

	switch header := postBody.Header.Get("Content-Type"); {
	case strings.HasPrefix(header, "application/json"):
		tokenResp := ReturnBodyRule{}
		decoder := json.NewDecoder(postBody.Body)
		if decodeErr := decoder.Decode(&tokenResp); decodeErr == nil {
			l.Print("json解密-PostScene", decodeErr)
			//log.WithFields(log.Fields{"error": decodeErr, "token": tokenResp}).Warn("json解密-PostScene")
			return "", decodeErr
		}
	case strings.HasPrefix(header, "image"):
		reply, readAllErr := ioutil.ReadAll(postBody.Body)
		l.Print("读取返回数据-PostScene-before")
		if readAllErr != nil {
			l.Print("读取返回数据-PostScene")
			//log.WithFields(log.Fields{"error": readAllErr}).Warn("读取返回数据-PostScene")
			return "", jsonErr
		}

		imageContent, createErr := os.Create(localPath)
		if createErr != nil {
			l.Print("打开本地文件-PostScene")
			//log.WithFields(log.Fields{"error": createErr, "imageContent": imageContent}).Warn("打开本地文件-PostScene")
			return "", createErr
		}

		writeStringRes, writeStringErr := io.WriteString(imageContent, string(reply))
		if writeStringErr != nil {
			l.Print("写入本地文件-PostScene", writeStringRes)
			//log.WithFields(log.Fields{"error": writeStringErr, "writeStringRes": writeStringRes}).Warn("写入本地文件-PostScene")
			return "", writeStringErr
		}

		closeErr := imageContent.Close()
		if closeErr != nil {
			l.Print("关闭本地文件-PostScene")
			// log.WithFields(log.Fields{"error": closeErr}).Warn("关闭本地文件-PostScene")
			return "", closeErr
		}
	default:
		l.Print("响应头获取-PostScene")
		//log.WithFields(log.Fields{"error": header}).Warn("响应头获取-PostScene")
		return "", errors.New("响应头获取失败-PostScene")
	}

	//newFilename := strconv.FormatInt(time.Now().Unix(), 10) + ".jpg"
	//fileName
	//newFilename := "qrcode/" + fileName + ".jpg"
	//url = common.QiniuUtil.UploadQiNiu(newFilename, localPath, systemConfig)
	l.Print("上传七牛的结果")
	l.Print(url)
	//ossFilePath, ossFileErr := UploadOssFile(localPath, imagePath)
	//return ossFilePath, ossFileErr
	return url, nil
}

var WechatService = &wechatService{}
